package cn.changein.framework.modular.system.service;

import cn.changein.framework.base.auth.context.LoginContextHolder;
import cn.changein.framework.base.auth.model.LoginUser;
import cn.changein.framework.base.pojo.node.MenuNode;
import cn.changein.framework.base.pojo.page.PageFactory;
import cn.changein.framework.core.constant.Const;
import cn.changein.framework.core.constant.factory.ConstantFactory;
import cn.changein.framework.core.constant.state.ManagerStatus;
import cn.changein.framework.core.exception.enumeration.BizExceptionEnum;
import cn.changein.framework.core.util.DefaultImages;
import cn.changein.framework.core.util.SaltUtil;
import cn.changein.framework.datascope.DataScope;
import cn.changein.framework.kernel.model.exception.ServiceException;
import cn.changein.framework.modular.system.entity.Role;
import cn.changein.framework.modular.system.entity.User;
import cn.changein.framework.modular.system.factory.UserFactory;
import cn.changein.framework.modular.system.mapper.UserMapper;
import cn.changein.framework.modular.system.model.UserDTO;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 管理员表 服务实现类
 *

 * @date: 2020-02-20
 * @copyright: 广州澄境科技有限公司
 */
@Service
public class UserService extends ServiceImpl<UserMapper, User> {

    @Autowired
    private MenuService menuService;

    @Autowired
    RoleService roleService;

    /**
     * 添加用戶
     *
     * @param user
     */
    @Transactional(rollbackFor = Exception.class)
    public void addUser(UserDTO user) {

        // 判断账号是否重复
        User theUser = this.getByAccount(user.getAccount());
        if (theUser != null) {
            throw new ServiceException(BizExceptionEnum.USER_ALREADY_REG);
        }

        // 完善账号信息
        String salt = SaltUtil.getRandomSalt();
        String password = SaltUtil.md5Encrypt(user.getPassword(), salt);

        User newUser = UserFactory.createUser(user, password, salt);
        this.save(newUser);

    }

    /**
     * 修改用户
     *
     * @param user
     */
    @Transactional(rollbackFor = Exception.class)
    public void editUser(UserDTO user) {
        User oldUser = this.getById(user.getUserId());

        if (LoginContextHolder.getContext().hasRole(Const.ADMIN_NAME)) {
            this.updateById(UserFactory.editUser(user, oldUser));
        } else {
            this.assertAuth(user.getUserId());
            LoginUser shiroUser = LoginContextHolder.getContext().getUser();
            if (shiroUser.getId().equals(user.getUserId())) {
                this.updateById(UserFactory.editUser(user, oldUser));
            } else {
                throw new ServiceException(BizExceptionEnum.NO_PERMITION);
            }
        }

    }

    /**
     * 删除用户
     *
     * @param userId
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteUser(Long userId) {

        //不能删除超级管理员
        if (userId.equals(Const.ADMIN_ID)) {
            throw new ServiceException(BizExceptionEnum.CANT_DELETE_ADMIN);
        }
        this.assertAuth(userId);
        this.setStatus(userId, ManagerStatus.DELETED.getCode());

    }

    /**
     * 修改用户状态
     *
     * @param userId
     * @param status
     * @return
     */
    public int setStatus(Long userId, String status) {
        return this.baseMapper.setStatus(userId, status);
    }

    /**
     * 修改密码
     *
     * @param oldPassword
     * @param newPassword
     */
    public void changePwd(String oldPassword, String newPassword) {
        Long userId = LoginContextHolder.getContext().getUser().getId();
        User user = this.getById(userId);

        String oldMd5 = SaltUtil.md5Encrypt(oldPassword, user.getSalt());

        if (user.getPassword().equals(oldMd5)) {
            String newMd5 = SaltUtil.md5Encrypt(newPassword, user.getSalt());
            user.setPassword(newMd5);
            this.updateById(user);
        } else {
            throw new ServiceException(BizExceptionEnum.OLD_PWD_NOT_RIGHT);
        }
    }

    /**
     * 根据条件查询用户列表
     *
     * @param dataScope
     * @param name
     * @param beginTime
     * @param endTime
     * @param deptId
     * @return
     */
    public Page<Map<String, Object>> selectUsers(DataScope dataScope, String name, String beginTime, String endTime, Long deptId) {
        Page page = PageFactory.defaultPage();
        Page<Map<String, Object>> mapPage = this.baseMapper.selectUsers(page, dataScope, name, beginTime, endTime, deptId);
        mapPage.getRecords().forEach(stringObjectMap -> {
            stringObjectMap.put("currentUser", false);
            Long userId = (Long) stringObjectMap.get("userId");
            Long id = LoginContextHolder.getContext().getUser().getId();
            if (userId.equals(id)) {
                stringObjectMap.put("currentUser", true);
            }
        });
        return mapPage;
    }

    /**
     * 设置用户的角色
     *
     * @param userId
     * @param roleIds
     * @return
     */
    public int setRoles(Long userId, String roleIds) {
        return this.baseMapper.setRoles(userId, roleIds);
    }

    /**
     * 通过账号获取用户
     *
     * @param account
     * @return
     */
    public User getByAccount(String account) {
        return this.baseMapper.getByAccount(account);
    }

    /**
     * 获取用户菜单列表
     *
     * @param roleList
     * @return
     */
    public List<Map<String, Object>> getUserMenuNodes(List<Long> roleList) {
        if (roleList == null || roleList.size() == 0) {
            return new ArrayList<>();
        } else {
            List<MenuNode> menus = menuService.getMenusByRoleIds(roleList, "Y");

            //定义不同系统分类的菜单集合
            ArrayList<Map<String, Object>> lists = new ArrayList<>();

            //根据当前用户包含的系统类型，分类出不同的菜单
            List<Map<String, Object>> systemTypes = LoginContextHolder.getContext().getUser().getSystemTypes();
            if (systemTypes != null) {
                for (Map<String, Object> systemType : systemTypes) {

                    //当前遍历系统分类code
                    String systemCode = (String) systemType.get("code");

                    //获取当前系统分类下菜单集合
                    ArrayList<MenuNode> originSystemTypeMenus = new ArrayList<>();
                    for (MenuNode menu : menus) {
                        if (menu.getSystemType().equals(systemCode)) {
                            originSystemTypeMenus.add(menu);
                        }
                    }

                    //拼接存放key为系统分类编码，value为该分类下菜单集合的map
                    HashMap<String, Object> map = new HashMap<>();
                    List<MenuNode> treeSystemTypeMenus = MenuNode.buildTitle(originSystemTypeMenus);
                    map.put("systemType", systemCode);
                    map.put("menus", treeSystemTypeMenus);
                    lists.add(map);
                }
            }
            return lists;
        }
    }

    /**
     * 判断当前登录的用户是否有操作这个用户的权限
     *
     * @param userId
     */
    public void assertAuth(Long userId) {
        if (LoginContextHolder.getContext().isAdmin()) {
            return;
        }
        List<Long> deptDataScope = LoginContextHolder.getContext().getDeptDataScope();
        User user = this.getById(userId);
        Long deptId = user.getDeptId();
        if (deptDataScope.contains(deptId)) {
            return;
        } else {
            throw new ServiceException(BizExceptionEnum.NO_PERMITION);
        }
    }

    /**
     * 刷新当前登录用户的信息
     */
    public void refreshCurrentUser() {
        //TODO 刷新
    }

    /**
     * 获取用户的基本信息
     *
     * @param userId
     * @return
     */
    public UserDTO getUserInfo(Long userId) {
        User user = this.getById(userId);
        Map<String, Object> map = UserFactory.removeUnSafeFields(user);
        String roleId = user.getRoleId();
        boolean adminFlag = false;
        if (StringUtils.isNotBlank(roleId)) {
            List<String> idsList = Lists.newArrayList(roleId.split(","));
            List<Role> roles = roleService.listByIds(idsList);
            adminFlag = roles.stream().anyMatch(role -> {
                return role.getAdminFlag() == 1;
            });
        }
        UserDTO userDTO = new UserDTO();
        BeanUtil.copyProperties(map, userDTO);
        userDTO.setRoleName(ConstantFactory.me().getRoleName(user.getRoleId()));
        userDTO.setDeptName(ConstantFactory.me().getDeptName(user.getDeptId()));
        userDTO.setAdminFlag(adminFlag ? 1 : 0);
        return userDTO;
    }

    /**
     * 获取用户首页信息
     *
     * @return
     */
    public Map<String, Object> getUserIndexInfo() {

        //获取当前用户角色列表
        LoginUser user = LoginContextHolder.getContext().getUser();
        List<Long> roleList = user.getRoleList();

        //用户没有角色无法显示首页信息
        if (roleList == null || roleList.size() == 0) {
            return null;
        }

        List<Map<String, Object>> menus = this.getUserMenuNodes(roleList);

        HashMap<String, Object> result = new HashMap<>();
        result.put("menus", menus);
        result.put("avatar", DefaultImages.defaultAvatarUrl());
        result.put("name", user.getName());

        return result;
    }

    /**
     * 选择办理人
     *
     * @param pageContext
     * @return
     */
    public IPage listUserAndRoleExpectAdmin(Page pageContext) {
        return baseMapper.listUserAndRoleExpectAdmin(pageContext);
    }
}

